home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1999 #2 / Amiga Plus CD - 1999 - No. 2.iso / System-Boost / Workbench / Archive / PP_v1.4 / Source / newstuff.c < prev    next >
C/C++ Source or Header  |  1998-11-08  |  4KB  |  158 lines

  1. /* Modified version of Nico's ppLoadData */
  2.  
  3. #include <pragmas.h>
  4. #include <libraries/dosextens.h>
  5. #include <exec/memory.h>
  6.  
  7. #define SAFETY    8    /* Safety decrunch margin */
  8.  
  9. extern int pp_DecrunchBuffer(UBYTE *,UBYTE *,int *);
  10. extern UBYTE *fragallocabs(int,int,UBYTE *);
  11. extern void fragfree(UBYTE *,int,int);
  12.  
  13. #asm
  14. ;
  15. ; What follows is Nico's own decrunch routine (v2.0). I couldn't get the
  16. ; in-library version to work. How about fixing the .fd file, Nico?!
  17. ;
  18. ; The code has undergone some optimization and application-speciffic
  19. ; modification by myself. Nothing too radical, but should do better than
  20. ; Nico's own code in most cases. Considered doing a Forbid() around tight
  21. ; loops, but dropped the idea (too hostile towards the rest of the system).
  22. ;
  23.  
  24. _pp_DecrunchBuffer:
  25.         movem.l    d2-d7/a2-a3/a5,-(sp)    ; /mich: Only preserve
  26.         move.l    36+4(a7),a0        ;        relevant registers
  27.         move.l    36+8(a7),a3
  28.         move.l    36+12(a7),a5
  29. ;                    ' /mich: dropped 'move.l 36+16(a7),a6'
  30.         bsr.s    Decrunch
  31.         movem.l    (sp)+,d2-d7/a2-a3/a5
  32.         rts
  33.  
  34. ; a3 -> file, a0 -> longword after crunched, a5 -> ptr to eff.
  35. ; destroys a0-a6 and d0-d7 (/mich: no longer entirely true)
  36. Decrunch:    moveq    #3,d6
  37.         moveq    #7,d7
  38.         moveq    #1,d5
  39.         move.l    d5,d4        ; /mich: Constant '#1' in d4
  40.         move.l    a3,a2        ; remember start of file
  41.         move.l    -(a0),d1    ; get file length and empty bits
  42.         tst.b    d1
  43.         beq.s    NoEmptyBits
  44.         bsr.s    ReadBit        ; this will always get the next long (D5 = 1)
  45.         sub.b    d4,d1        ; /mich: Use constant '#1'
  46.         lsr.l    d1,d5        ; get rid of empty bits
  47. NoEmptyBits:    lsr.l    #8,d1
  48.         add.l    d1,a3        ; a3 = endfile
  49. CheckCrunch:    bsr.s    ReadBit        ; check if crunch or normal
  50.         bcs.s    CrunchedBytes
  51. NormalBytes:    moveq    #0,d2
  52. Read2BitsRow:    move.l    d4,d0        ; /mich: Use constant '#1'
  53.         bsr.s    ReadD1
  54.         add.w    d1,d2
  55.         cmp.w    d6,d1
  56.         beq.s    Read2BitsRow
  57. ReadNormalByte:    moveq    #7,d0
  58.         bsr.s    ReadD1
  59.         move.b    d1,-(a3)
  60.         dbf    d2,ReadNormalByte
  61.         cmp.l    a3,a2
  62.         bcs.s    CrunchedBytes
  63.         rts
  64.  
  65. ReadBit:    lsr.l    d4,d5        ; this will also set X if d5 becomes zero
  66.         beq.s    GetNextLong    ; /mich: Use constant '#1' (previous line)
  67.         rts
  68.  
  69. GetNextLong:    move.l    -(a0),d5
  70.         roxr.l    d4,d5        ; X-bit set by lsr above
  71.         rts            ; /mich: Use constant '#1' (previous line)
  72.  
  73. ReadD1sub:    sub.w    d4,d0        ; /mich: Use constant '#1'
  74. ReadD1:        moveq    #0,d1
  75. ReadBits:    lsr.l    d4,d5        ; this will also set X if d5 becomes zero
  76.         beq.s    GetNext        ; /mich: Use constant '#1' (previous line)
  77. RotX:        roxl.l    d4,d1        ; /mich: Use constant '#1'
  78.         dbf    d0,ReadBits
  79.         rts
  80.  
  81. GetNext:    move.l    -(a0),d5
  82.         roxr.l    d4,d5        ; X-bit set by lsr above
  83.         bra.s    RotX        ; /mich: Use constant '#1' (prev line)
  84.  
  85. CrunchedBytes:    move.l    d4,d0        ; /mich: Use constant '#1'
  86.         bsr.s    ReadD1        ; read code
  87.         moveq    #0,d0
  88.         move.b    0(a5,d1.w),d0    ; get number of bits of offset
  89.         move.w    d1,d2        ; d2 = code = length-2
  90.         cmp.w    d6,d2        ; if d2 = 3 check offset bit and read length
  91.         bne.s    ReadOffset
  92.         bsr.s    ReadBit        ; read offset bit (long/short)
  93.         bcs.s    LongBlkOffs
  94.         moveq    #7,d0
  95. LongBlkOffs:    bsr.s    ReadD1sub
  96.         move.w    d1,d3        ; d3 = offset
  97. Read3BitsRow:    moveq    #2,d0
  98.         bsr.s    ReadD1
  99.         add.w    d1,d2        ; d2 = length-1
  100.         cmp.w    d7,d1        ; cmp with #7
  101.         beq.s    Read3BitsRow
  102.         bra.s    DecrunchBlock
  103.  
  104. ReadOffset:    bsr.s    ReadD1sub    ; read offset
  105.         move.w    d1,d3        ; d3 = offset
  106. DecrunchBlock:    add.w    d4,d2        ; /mich: Use constant '#1'
  107. 1$        move.b    0(a3,d3.w),-(a3)
  108.         dbf    d2,1$
  109. EndOfLoop:                ; /mich: dropped 'move.w a3,(a6)'
  110.         cmp.l    a3,a2
  111.         bcs    CheckCrunch
  112.         rts
  113. #endasm
  114.  
  115. myPPLoadData(register BPTR filehandle,register UBYTE **mem,register *size)
  116. {
  117.     int efficiency,decrunched;
  118.     register crunlen;
  119.     register UBYTE *memgot;
  120.     register returnval = 1;
  121.  
  122.     Read(filehandle,(char *)&efficiency,sizeof(int));
  123.     Seek(filehandle,-sizeof(int),OFFSET_END);
  124.     Read(filehandle,(char *)&decrunched,sizeof(int));
  125.  
  126.     if (memgot = AllocMem((decrunched >>= 8) + SAFETY,MEMF_PUBLIC))
  127.     {
  128.         UBYTE *filebody;
  129.  
  130.         Forbid();
  131.         FreeMem(memgot,decrunched + SAFETY);
  132.         filebody = fragallocabs(decrunched,10240,memgot+SAFETY);
  133.         memgot   = AllocAbs(SAFETY,memgot);
  134.         Permit();
  135.  
  136.         crunlen = Seek(filehandle,8,OFFSET_BEGINNING) - 8;
  137.  
  138.         if (Read(filehandle,(char *)memgot,crunlen) == crunlen)
  139.         {
  140.             pp_DecrunchBuffer(memgot+crunlen,memgot+SAFETY,&efficiency);
  141.  
  142.             FreeMem(memgot,SAFETY);
  143.  
  144.             *mem  = filebody;
  145.             *size = decrunched;
  146.  
  147.             returnval = 0;
  148.         }
  149.         else
  150.         {
  151.             FreeMem(memgot,SAFETY);
  152.             fragfree(filebody,decrunched,10240);
  153.         }
  154.     }
  155.  
  156.     return(returnval);
  157. }
  158.